#!/bin/bash

source /home/shell/util.sh

# 服务Type设置
printInfo "请选择服务类型："
echo -e "\033[96m\033[1m1. simple\033[0m     (服务将立即启动服务进程不会fork)"
echo -e "\033[96m\033[1m2. forking\033[0m    (当该服务进程fork，且父进程退出后服务启动成功)"
echo -e "\033[96m\033[1m3. oneshot\033[0m    (适用于只执行一项任务、随后立即退出的服务)"
echo -e "\033[96m\033[1m4. notify\033[0m     (与simple相同，但约定服务会在就绪后向 systemd 发送一个信号)"
echo -e "\033[96m\033[1m5. dbus\033[0m       (当指定的 BusName 出现在DBus系统总线上时，systemd认为服务就绪)"
echo -e "\033[96m\033[1m6. idle\033[0m       (等待所有任务处理完成后，才开始执行idle类型的单元。其他行为与simple类似)"
read -p "[默认 1. simple]:" service_type_num
service_type_num=${service_type_num:-"1"};
case "${service_type_num}" in
    1)
        service_type="simple"
    ;;
    2)
        service_type="forking"
    ;;
    3)
        service_type="oneshot"
    ;;
    4)
        service_type="notify"
    ;;
    5)
        service_type="dbus"
    ;;
    6)
        service_type="idle"
    ;;
    *)
        service_type="simple"
    ;;
esac

# 服务killMode设置
printInfo "选择killMode："
echo -e "\033[96m\033[1m1. control-group\033[0m    表示杀死该单元的 cgroup 内的所有进程(对于 service 单元，还要先执行 ExecStop= 动作)"
echo -e "\033[96m\033[1m2. process\033[0m          表示仅杀死主进程"
echo -e "\033[96m\033[1m3. mixed\033[0m            表示首先向主进程发送 SIGTERM 信号，然后再向该单元的 cgroup 内的所有其他进程发送 SIGKILL 信号"
echo -e "\033[96m\033[1m4. none\033[0m             表示仅执行 ExecStop= 动作， 而不杀死任何进程。 这会导致即使单元已经停止， 但是该单元的 cgroup 依然一直存在， 直到其中的进程 全部死亡。"
read -p "[默认 1. control-group]：" kill_mode_num
kill_mode_num=${kill_mode_num:-"1"};
case "${kill_mode_num}" in
    1)
        kill_mode="control-group"
    ;;
    2)
        kill_mode="process"
    ;;
    3)
        kill_mode="mixed"
    ;;
    4)
        kill_mode="none"
    ;;
    *)
        kill_mode="control-group"
    ;;
esac

# 日志输出配置
printInfo "选择日志输出格式："
echo -e "\033[96m\033[1m1. inherit\033[0m            (表示继承 StandardInput= 的值)"
echo -e "\033[96m\033[1m2. null\033[0m               (表示 /dev/null ， 也就是所有输出都会被丢弃)"
echo -e "\033[96m\033[1m3. tty\033[0m                (表示 TTY(由 TTYPath= 设置)。 如果仅用于输出，那么进程将无需取得终端的控制权， 亦无需等待其他进程释放终端控制权)"
echo -e "\033[96m\033[1m4. journal\033[0m            (表示 systemd 日志服务(通过 journalctl(1) 访问)。 注意，所有发到 syslog 或 kmsg 的日志都会隐含的复制一份到 journal 中)"
echo -e "\033[96m\033[1m5. syslog\033[0m             (表示 syslog(3) 日志服务。 注意，此时所有日志都会隐含的复制一份到 journal 中。)"
echo -e "\033[96m\033[1m6. kmsg\033[0m               (表示内核日志缓冲区(通过 dmesg(1) 访问)。 注意，此时所有日志都会隐含的复制一份到 journal 中)"
echo -e "\033[96m\033[1m7. journal+console\033[0m    (与上面三个值类似，不同之处在于所有日志都会再复制一份到系统的控制台上)"
echo -e "\033[96m\033[1m8. syslog+console\033[0m     (与上面三个值类似，不同之处在于所有日志都会再复制一份到系统的控制台上)"
echo -e "\033[96m\033[1m9. kmsg+console\033[0m       (与上面三个值类似，不同之处在于所有日志都会再复制一份到系统的控制台上)"
echo -e "\033[96m\033[1m10. file:path\033[0m         (用于将指定的文件系统对象连接到标准输出。 其含义与上文 StandardInput= 中的解释完全相同。 如果 path 是文件系统上的一个普通文件， 那么它将被打开(若不存在则创建)， 并从头开始写入(但并不清空已有内容)。 如果将标准输入与标准输出都指定为同一个文件，那么此文件仅打开一次，并同时用于输入与输出。 这种用法主要用于文件系统上的 AF_UNIX 套接字，因为在这种情况下， 只能创建一个同时用于输入与输出的流连接。)"
echo -e "\033[96m\033[1m11. append:path\033[0m       (与 file:path 类似，不同之处仅在于以附加(append)模式打开文件。)"
echo -e "\033[96m\033[1m12. socket\033[0m            (仅可用于基于套接字启动的服务单元。 其含义与上文 StandardInput= 中的解释完全相同。)"
echo -e "\033[96m\033[1m13. fd:name\033[0m           (将标准输出连接到某个套接字单元提供的名为 name 的文件描述符。 省略 name 表示使用隐含的默认名称 "stdout" (也就是 "fd" 等价于 "fd:stdout")。 必须通过套接字单元的 Sockets= 选项定义至少一个指定名称的文件描述符， 并且文件描述符的名称可以与定义它的套接字单元的名称不同。 如果找到多个匹配的文件描述符，那么仅使用第一个匹配项。详见 systemd.socket(5) 手册中的 FileDescriptorName= 选项， 以了解有关命名文件描述符及其顺序的详细信息。)"
read -p "[默认 4. journal]：" sys_log_num
sys_log_num=${sys_log_num:-"4"};
case "${sys_log_num}" in
    1)
        sys_log_value="inherit"
    ;;
    2)
        sys_log_value="null"
    ;;
    3)
        sys_log_value="tty"
    ;;
    4)
        sys_log_value="journal"
    ;;
    5)
        sys_log_value="syslog"
    ;;
    6)
        sys_log_value="kmsg"
    ;;
    7)
        sys_log_value="journal+console"
    ;;
    8)
        sys_log_value="syslog+console"
    ;;
    9)
        sys_log_value="kmsg+console"
    ;;
    10|11)
        read -p "日志目录[默认 /var/log]：" sys_log_dir
        sys_log_dir=${sys_log_dir:-"/var/log"}
        if [ ! -d "${sys_log_dir}" ]; then
            mkdir -p ${sys_log_dir}
        fi
    ;;
    12)
        sys_log_value="socket"
    ;;
    13)
        sys_log_value="fd:name"
    ;;
    *)
        sys_log_value="journal"
    ;;
esac

read -p "输入服务名称：" service_name
read -p "输入服务启动命令：" start_cmd
read -p "输入服务启动后执行命令：" exec_start_post
read -p "输入服务重启命令：" restart_cmd
read -p "输入服务停止命令：" stop_cmd
read -p "运行用户：" run_as_user

tee /etc/systemd/system/${service_name}.service <<EOF
[Unit]
Description=${service_name} service power by jlcon
After=network.target sshd-keygen.service

[Service]
Type=${service_type}
KillMode=${kill_mode}
Environment=
EnvironmentFile=
ExecStart=${start_cmd}
EOF

if [[ -n "${exec_start_post}" ]]; then
tee /etc/systemd/system/${service_name}.service -a<<EOF
ExecStartPost=${exec_start_post}
EOF
fi

if [[ -n "${stop_cmd}" ]]; then
tee /etc/systemd/system/${service_name}.service -a<<EOF
ExecStop=${stop_cmd}
EOF
fi

if [[ -n "${restart_cmd}" ]]; then
tee /etc/systemd/system/${service_name}.service -a<<EOF
ExecReload=${restart_cmd}
EOF
fi

if [[ -n "${run_as_user}" ]]; then
tee /etc/systemd/system/${service_name}.service -a<<EOF
User=${run_as_user}
EOF
fi

# 设置日志
case "${sys_log_num}" in
    10)
tee /etc/systemd/system/${service_name}.service -a<<EOF
StandardOutput=file:${sys_log_dir}/${service_name}-info.log
StandardError=inherit
EOF
    ;;
    11)
tee /etc/systemd/system/${service_name}.service -a<<EOF
StandardOutput=append:${sys_log_dir}/${service_name}-info.log
StandardError=inherit
EOF
    ;;
    *)
tee /etc/systemd/system/${service_name}.service -a<<EOF
StandardOutput=${sys_log_value}
StandardError=inherit
EOF
    ;;
esac


tee /etc/systemd/system/${service_name}.service -a<<EOF

[Install]
WantedBy=multi-user.target
EOF

chmod +x /etc/systemd/system/${service_name}.service
cat /etc/systemd/system/${service_name}.service
systemctl daemon-reload
systemctl list-unit-files --type=service --all|grep ${service_name}
systemctl enable --now ${service_name}
systemctl status ${service_name}